// WebSocket下载服务 - 重构为支持多实例
class DownloadWebSocketService {
  /**
   * 构造函数
   * @param {string} wsUrl - WebSocket连接的URL字符串
   * @param {object} options - 配置对象
   * @param {number} options.id - 标识ID
   * @param {number} options.packageSize - 包大小
   * @param {number} options.stepSize - 步长
   * @param {number} options.plantId - 工厂ID
   * @param {number} options.plantType - 工厂类型
   * @param {number} options.copyNum - 副本编号
   */
  constructor(wsUrl, options = {}) {
    // 验证必需参数
    if (!wsUrl) {
      throw new Error("WebSocket URL is required");
    }

    // 存储配置参数
    this.wsUrl = wsUrl;
    this.options = {
      id: options.id || 29649,
      packageSize: options.packageSize || 10,
      stepSize: options.stepSize || 0.04,
      plantId: options.plantId || 68,
      plantType: options.plantType || 1,
      copyNum: options.copyNum || 0,
    };

    // 初始化WebSocket实例
    this.ws = null;
    // 连接状态
    this.isConnected = false;
    // 消息队列，用于存储连接未建立时的消息
    this.messageQueue = [];
    // 重连尝试次数
    this.reconnectAttempts = 0;
    // 最大重连尝试次数
    this.maxReconnectAttempts = 0;
    // 重连间隔时间(ms)
    this.reconnectInterval = 3000;
    // 事件回调函数存储
    this.callbacks = {
      onOpen: [],
      onMessage: [],
      onError: [],
      onClose: [],
    };

    // 自动连接
    this.connect();
  }

  /**
   * 建立WebSocket连接
   */
  connect() {
    // 如果已连接，则不再重复连接
    if (this.ws && this.isConnected) {
      return;
    }

    try {
      // 创建WebSocket实例
      this.ws = new WebSocket(this.wsUrl);

      /**
       * 连接打开事件处理
       */
      this.ws.onopen = (event) => {
        console.log("算法模型开始下载");
        this.isConnected = true;
        this.reconnectAttempts = 0;

        // 发送初始化消息
        this.sendInitialMessage();

        // 处理消息队列中的消息
        this.flushMessageQueue();

        // 触发onOpen回调
        this.callbacks.onOpen.forEach((callback) => callback(event));
      };

      /**
       * 接收消息事件处理
       */
      this.ws.onmessage = (event) => {
        // console.log("收到WebSocket消息:", event.data);
        this.callbacks.onMessage.forEach((callback) => callback(event));
      };

      /**
       * 错误处理
       */
      this.ws.onerror = (error) => {
        console.error("WebSocket错误:", error);
        this.callbacks.onError.forEach((callback) => callback(error));
      };

      /**
       * 连接关闭处理
       */
      this.ws.onclose = (event) => {
        console.log("算法模型已下载完成");
        this.isConnected = false;
        this.callbacks.onClose.forEach((callback) => callback(event));

        // 尝试重连
        this.attemptReconnect();
      };
    } catch (error) {
      console.error("WebSocket连接失败:", error);
      this.attemptReconnect();
    }
  }

  /**
   * 发送初始化消息（连接建立时自动调用）
   */
  sendInitialMessage() {
    // 导入store以获取IP地址
    import("../store/ws.js")
      .then(({ useWsStore }) => {
        const wsStore = useWsStore();

        // 获取IP地址和服务器URL
        const ip = wsStore.getIpFromUrl;
        const serverUrl = wsStore.getServerUrl;

        // 构建初始化消息
        const initMessage = {
          id: this.options.id,
          packageSize: this.options.packageSize,
          stepSize: this.options.stepSize,
          plantId: this.options.plantId,
          plantType: this.options.plantType,
          copyNum: this.options.copyNum,
          downloadPort: 18000 + this.options.copyNum,
          monitorPort: 19000 + this.options.copyNum,
          ip: ip,
          serverUrl: serverUrl,
        };

        // 发送JSON格式的消息
        this.send(JSON.stringify(initMessage));
        console.log("初始化消息已发送:", initMessage);
      })
      .catch((error) => {
        console.error("导入store失败:", error);

        // 如果store导入失败，使用备选方案获取IP
        const ip = this.extractIpFromUrl(this.wsUrl);
        const initMessage = {
          id: this.options.id,
          packageSize: this.options.packageSize,
          stepSize: this.options.stepSize,
          plantId: this.options.plantId,
          plantType: this.options.plantType,
          copyNum: this.options.copyNum,
          downloadPort: 18000 + this.options.copyNum,
          monitorPort: 19000 + this.options.copyNum,
          ip: ip,
          serverUrl: ` ${ip} :8070/rtlab`,
        };

        this.send(JSON.stringify(initMessage));
        console.log("初始化消息已发送（备选方案）:", initMessage);
      });
  }

  /**
   * 从URL中提取IP地址（备选方案）
   * @param {string} url - WebSocket URL
   * @returns {string} IP地址
   */
  extractIpFromUrl(url) {
    try {
      const urlObj = new URL(url);
      return urlObj.hostname;
    } catch (error) {
      // 如果URL解析失败，尝试从字符串中提取IP
      const ipMatch = url.match(/(\d+\.\d+\.\d+\.\d+)/);
      return ipMatch ? ipMatch[1] : "localhost";
    }
  }

  /**
   * 发送消息到WebSocket服务器
   * @param {string|object} message - 要发送的消息
   */
  send(message) {
    // 如果消息是对象，转换为JSON字符串
    const messageToSend =
      typeof message === "object" ? JSON.stringify(message) : message;

    // 如果已连接且WebSocket处于OPEN状态，则直接发送
    if (this.isConnected && this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(messageToSend);
    } else {
      // 否则将消息加入队列，等待连接建立后发送
      console.warn("WebSocket未连接，消息已加入队列");
      this.messageQueue.push(messageToSend);
      // 尝试重新连接
      this.connect();
    }
  }

  /**
   * 清空消息队列，发送所有积压的消息
   */
  flushMessageQueue() {
    while (this.messageQueue.length > 0) {
      const message = this.messageQueue.shift();
      this.send(message);
    }
  }

  /**
   * 尝试重新连接WebSocket
   */
  attemptReconnect() {
    if (this.reconnectAttempts < this.maxReconnectAttempts) {
      this.reconnectAttempts++;
      console.log(
        `尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`
      );

      setTimeout(() => {
        this.connect();
      }, this.reconnectInterval);
    } else {
      console.error("WebSocket重连失败，已达到最大重试次数");
    }
  }

  /**
   * 断开WebSocket连接
   */
  disconnect() {
    if (this.ws) {
      this.ws.close();
      this.ws = null;
      this.isConnected = false;
      this.messageQueue = [];
      this.reconnectAttempts = 0;
    }
  }

  /**
   * 注册事件回调
   * @param {string} event - 事件类型 (onOpen, onMessage, onError, onClose)
   * @param {Function} callback - 回调函数
   */
  on(event, callback) {
    if (!this.callbacks[event]) {
      this.callbacks[event] = [];
    }
    this.callbacks[event].push(callback);
  }

  /**
   * 移除事件回调
   * @param {string} event - 事件类型
   * @param {Function} callback - 要移除的回调函数
   */
  off(event, callback) {
    if (this.callbacks[event]) {
      this.callbacks[event] = this.callbacks[event].filter(
        (cb) => cb !== callback
      );
    }
  }

  /**
   * 获取当前连接状态
   * @returns {boolean} 连接状态
   */
  getConnectionStatus() {
    return this.isConnected;
  }

  /**
   * 获取当前配置选项
   * @returns {object} 配置对象
   */
  getOptions() {
    return { ...this.options };
  }

  /**
   * 获取WebSocket URL
   * @returns {string} WebSocket URL
   */
  getUrl() {
    return this.wsUrl;
  }

  /**
   * 更新配置选项
   * @param {object} newOptions - 新的配置选项
   */
  updateOptions(newOptions) {
    this.options = { ...this.options, ...newOptions };
  }

  /**
   * 连接打开事件监听器
   * @param {Function} callback - 回调函数
   */
  onopen(callback) {
    this.on("onOpen", callback);
  }

  /**
   * 接收消息事件监听器
   * @param {Function} callback - 回调函数
   */
  onmessage(callback) {
    this.on("onMessage", callback);
  }

  /**
   * 错误事件监听器
   * @param {Function} callback - 回调函数
   */
  onerror(callback) {
    this.on("onError", callback);
  }

  /**
   * 连接关闭事件监听器
   * @param {Function} callback - 回调函数
   */
  onclose(callback) {
    this.on("onClose", callback);
  }
}

// 导出DownloadWebSocketService类，支持创建多个独立实例
export default DownloadWebSocketService;
